﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using log4net;
using Microsoft.Practices.ServiceLocation;
using SolrNet;
using SolrNet.Commands.Parameters;
using SolrNet.Impl;

namespace Sherwood.Content.UpdateServices.Solr
{
    public class SolrDocumentService<T> : ISearchDocumentService
        where T : ISearchDocument, new()
    {
        private static readonly ILog Log = LogManager.GetLogger(typeof(SolrDocumentService<T>));

        private readonly ISolrOperations<T> _solr;

        public SolrDocumentService(string serverUrl)
        {
            if(Log.IsInfoEnabled)
                Log.InfoFormat("Initializing connection to {0}", serverUrl);

            var connection = new SolrConnection(serverUrl);

            Startup.Init<T>(connection);

            _solr = ServiceLocator.Current.GetInstance<ISolrOperations<T>>();
        }

        public ISearchDocument CreateDocument(IRecord record)
        {
            if(Log.IsDebugEnabled)
                Log.DebugFormat("Creating document for record {0}", record.Id);

            var document = DependencyInjection.Resolve<ISearchDocument>();
            document.RecordId = record.Id;
            document.Source = record.Client.Id;
            document.Title = record.Title;
            document.Description = record.Description;
            document.CultureInvariantReferenceId = record.CultureInvariantReferenceId;
            document.CultureName = record.CultureName;
            document.LanguageCode = record.LanguageCode;
            return document;
        }

        public void PublishDocuments(IEnumerable<ISearchDocument> documents)
        {
            if (Log.IsDebugEnabled)
                Log.Debug("Publishing documents to solr server (" + string.Join(", ", documents.Select(d => d.RecordId.ToString())) + ")");
            
            var docs = documents.Cast<T>();

            // loop through all properties in document and strip any invalid xml characters
            foreach (var doc in docs)
            {
                foreach (var pi in typeof (T).GetProperties())
                {
                    if (pi.PropertyType == typeof (string) && pi.CanRead && pi.CanWrite)
                        pi.SetValue(doc, ((string) pi.GetValue(doc, null)).StripNonValidXmlCharacters(), null);
                }
            }

            _solr.Add(docs);
            _solr.Commit();
        }

        public void DeleteDocuments(IEnumerable<Guid> recordIds)
        {
            if (Log.IsDebugEnabled)
                Log.Debug("Deleting documents from solr server (" + string.Join(", ", recordIds + ")"));

            _solr.Delete(recordIds.Select(id => id.ToString()));
            _solr.Commit();
        }
    }
}
